package utp.tepc.jogogeneral;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Jogo
{
    private List<JogadorDado> jogadores;
    private IGeneral general;
    private int jogadorAtual;
    private int rodada;
    private boolean jogadaConlcuida = false;

    public Jogo()
    {
	this.jogadores = new ArrayList<JogadorDado>();
    }

    public JogadorDado getJogadorAtual()
    {
	return this.jogadores.get(jogadorAtual);
    }

    private void proxJogador()
    {
	this.jogadorAtual++;

	if (!(this.jogadorAtual < this.jogadores.size()))
	{
	    this.jogadorAtual = 0;
	    this.proxRodada();
	}
    }

    public IGeneral getGeneral()
    {
	return general;
    }

    private void proxRodada()
    {
	this.rodada++;
    }

    public boolean temLances()
    {
	if (this.general.temNovoLancamento(this.jogadores.get(jogadorAtual).getQtdLances()))
	    return true;

	return false;
    }

    public boolean jogadaConcluida()
    {
	return this.jogadaConlcuida;
    }


    public void jogadorLanca() throws Exception
    {
	this.jogadores.get(this.jogadorAtual).lancarDados();
    }

    public String getValoresLanc() throws Exception
    {
	Pattern p = Pattern.compile("( :: )$");
	Matcher m;
	StringBuilder sb = new StringBuilder();
	int count = 1;

	for (Dado d : this.general.getDados())
	{
	    sb.append("[d-");
	    sb.append(count);
	    sb.append("] ");
	    sb.append(d.getNumeroSorteado());
	    sb.append(" :: ");
	    count++;
	}

	m = p.matcher(sb.toString());

	return "\n" + m.replaceAll("");
    }

    public void setDadosJogador() throws Exception
    {
	jogadores.get(jogadorAtual).setDados(this.general.getDados());
	this.jogadaConlcuida = false;
    }

    private void resetStatusDados()
    {
	for (Dado d : this.general.getDados())
	    d.setSeleciondao(false);
    }

    public void adcionarJogadorDado(JogadorDado j)
    {
	this.jogadores.add(j);
    }

    public List<JogadorDado> getJogadores()
    {
	return jogadores;
    }

    public void iniciarJogo() throws Exception
    {
	this.jogadorAtual = 0;
	this.rodada = 1;
	this.jogadaConlcuida = false;
	this.general = new General(this);
	this.resetStatusDados();

	if (this.jogadores.size() == 0)
	    throw new Exception("Inser alguns jogadores antes de iniciar o jogo.");
    }

    public boolean fimJogo()
    {
	return this.general.temNovaRodada(this.rodada);
    }

    public int getRodada()
    {
	return this.rodada;
    }

    public int getQtdLance()
    {
	return this.jogadores.get(jogadorAtual).getQtdLances();
    }

    public boolean marcarPontos(JogadorDado j, String jogada, Integer pontos) throws Exception
    {
	if (this.general.podeMarcarPonto(j.getPontuacao(), jogada))
	{
	    j.marcarPonto(new PontuacaoDado(j, jogada, pontos));
	    this.concluirJogada();
	    
	    return true;
	}

	return false;
    }

    private void concluirJogada()
    {
	this.jogadaConlcuida = true;
	this.jogadores.get(jogadorAtual).liberarDados();
	this.proxJogador();
    }
    
    private int totalPontoPorJogador(JogadorDado j)
    {
	int total = 0;
	
	for(PontuacaoDado p : j.getPontos())
	    total += p.getPonto();
	    
	return total;
    }
    
    public HashMap<String, Integer> getPlacar()
    {
	HashMap<String, Integer> list = new HashMap<String, Integer>();
	
	for(JogadorDado j : this.jogadores)
	    list.put(j.toString(), (Integer)totalPontoPorJogador(j));
	
	return list;
    }
    
    public String getVencedor(HashMap<String, Integer> placar)
    {
	String vencedor = "";
	Integer aux = 0;
	
	// pega o primeiro valor de pontos do placar
	for(String j : placar.keySet())
	{
	    aux = placar.get(j);
	    vencedor = j;
	    break;
	}
	
	for(String j : placar.keySet())
	{
	    if(placar.get(j) > aux)
	    {
		aux = placar.get(j);
		vencedor = j;
	    }
	}
	
	return vencedor + " com " + aux.toString() + " pontos";
    }
}
